package com.kpmg.datalake.autopackage.controller;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.ReentrantLock;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.Workbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.kpmg.datalake.autopackage.service.ExcelTemplateService;
import com.kpmg.datalake.autopackage.service.IndustryTemplateService;
import com.kpmg.datalake.autopackage.utils.ExcelOperateUtil;
import com.kpmg.datalake.autopackage.utils.MyThreadPoolExecutor;
import com.kpmg.datalake.autopackage.vo.ExcelTemplate;
import com.kpmg.datalake.autopackage.vo.IndustryTemplateDTO;
import com.kpmg.datalake.autopackage.vo.IndustryTemplateVO;
import com.kpmg.datalake.common.utils.ContextHolderUtils;
import com.kpmg.datalake.common.utils.ResponseUtils;
import com.kpmg.datalake.common.utils.Utils;
import com.kpmg.datalake.common.vo.ServerResponse;
import com.kpmg.datalake.db.model.Project;
import com.kpmg.datalake.db.model.SysUsr;
import com.kpmg.datalake.operatelog.annotation.OptLog;
import com.kpmg.datalake.operatelog.enums.LogTypeEnum;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;

/**
 * @Author: Richard.ji [richard.ji@kpmg.com]
 * @Date: 2018-07-12 16:02:31
 * @Description: 行业模板
 */

@RestController
@Api("PKGIndustryExcelController 行业模板")
@RequestMapping("/pkgIndustry")
public class PkgIndustryExcelController {
  private static final Logger LOG = LoggerFactory.getLogger(PkgIndustryExcelController.class);

  @Value("${template.path}")
  private String templatePath;

  private static final String UPLOAD = "upload";
  private static final String DESCRIPTION = "Description";
  private static final String SHEET_NAME = "sheetName";
  private static final String SPLIT_SIGN = ",";
  private static final String UPLOAD_UNFINISHED = "1";
  private static final String UPLOAD_FINISHED = "2";
  private static final String UPLOAD_ERROR = "3";

  @Autowired
  private IndustryTemplateService industryTemplateService;

  @Autowired
  private ExcelTemplateService excelTemplateService;

  /**
   * 线程池核心线程数
   */
  private static final int CORE_POOL_SIZE = 5;
  /**
   * 线程池最大线程数
   */
  private static final int MAX_POOL_SIZE = 10;
  /**
   * 额外线程空状态生存时间
   */
  private static final int KEEP_ALIVE_TIME = 30 * 1000;

  /**
   * 查询锁
   */
  private ReentrantLock queryLock = new ReentrantLock();

  /**
   * 阻塞队列。当核心线程都被占用,且阻塞队列已满的情况下,才会开启额外线程。
   */
  private static BlockingQueue<Runnable> workQueue = new LinkedBlockingQueue<>(CORE_POOL_SIZE);

  private static ThreadFactory factory = new ThreadFactory() {
    private final AtomicInteger integer = new AtomicInteger();

    @Override
    public Thread newThread(Runnable r) {
      return new Thread(r, "ThreadPool thread: " + integer.getAndIncrement());
    }
  };

  private static ThreadPoolExecutor threadPool = new MyThreadPoolExecutor(CORE_POOL_SIZE,
      MAX_POOL_SIZE, KEEP_ALIVE_TIME, TimeUnit.SECONDS, workQueue, factory);

  /**
   * 查询行业模板列表
   * 
   * @param industryTemplateVO
   * @return
   */
  @PostMapping(value = "/showIndustryRqsList")
  @OptLog(logType = LogTypeEnum.OPERATION, module = "autoPackage", description = "查询行业模板")
  public ServerResponse showIndustryRqsList(@RequestBody IndustryTemplateVO industryTemplateVO) {

    try {
      return industryTemplateService.getIndustryTemplateList(industryTemplateVO.getPageNum(),
          industryTemplateVO.getPageSize());

    } catch (Exception e) {
      LOG.error("行业模板列表展示异常:" + e.getMessage(), e);
      return ServerResponse.createByErrorMessage("行业模板列表展示异常");
    }
  }

  /**
   * 查询上传任务数
   * 
   * @return
   */
  @PostMapping(value = "/queryTaskCount")
  public ServerResponse queryTaskCount() {
    queryLock.lock();
    try {
      Integer count = industryTemplateService.queryTaskCount();

      return ServerResponse.createBySuccess(count);
    } catch (Exception e) {
      LOG.error("查询上传任务数异常:" + e.getMessage(), e);
    } finally {
      queryLock.unlock();
    }
    return ServerResponse.createBySuccess();
  }

  /**
   * 上传行业模板
   *
   * @param file
   * @return
   */
  @PostMapping(value = "/uploadIndustryTemplate")
  @OptLog(logType = LogTypeEnum.OPERATION, module = "autoPackage", description = "添加行业模板")
  public ServerResponse uploadIndustryTemplate(MultipartFile file, String fileName,
      String comments) {
    IndustryTemplateDTO industryTemplateDTO = new IndustryTemplateDTO();
    try {
      if (file != null) {
        SysUsr user = ContextHolderUtils.getLoginUser();

        String uploadPath = System.getProperty(templatePath);
        String absolutePath = ExcelOperateUtil.handleFileStream(file, uploadPath, user);

        industryTemplateDTO =
            handleIndustryTemplate(fileName, absolutePath, user.getUsrId(), comments);
        String tplId = industryTemplateDTO.getTplId();

        industryTemplateService.insertIndustryTemplate(industryTemplateDTO);

        threadPool.execute(() -> uploadTemplateThread(absolutePath, tplId));

        return ServerResponse.createBySuccess();
      } else {
        return ServerResponse.createByError();
      }
    } catch (Exception e) {
      LOG.error("上传行业模板异常:" + e.getMessage(), e);
      File dir = new File(industryTemplateDTO.getFileUrl());
      FileUtils.deleteQuietly(dir);
      return ServerResponse.createByErrorMessage("行业模板新增失败");
    }
  }

  /**
   * 新增行业模板
   * 
   * @param absolutePath
   * @param tplId
   */
  private void uploadTemplateThread(String absolutePath, String tplId) {
    IndustryTemplateDTO industryTemplateDTO = new IndustryTemplateDTO();
    try {
      Workbook workbook = ExcelOperateUtil.getWorkbook(absolutePath);
      String[] totalSheetArr = ExcelOperateUtil.getSheets(workbook);
      totalSheetArr = ArrayUtils.removeElement(totalSheetArr, DESCRIPTION);

      // 获取sheet页描述数组
      StringBuilder totalSheet = new StringBuilder();
      if (!ArrayUtils.isEmpty(totalSheetArr)) {
        Arrays.stream(totalSheetArr).forEach(arr -> totalSheet.append(arr).append(SPLIT_SIGN));
      }

      List<Map<String, String>> sheetList = getSheetList(workbook, totalSheetArr);

      if (!StringUtils.isEmpty(totalSheet)) {
        industryTemplateDTO
            .setTotalSheet(totalSheet.toString().substring(0, totalSheet.length() - 1));
      }
      if (!CollectionUtils.isEmpty(sheetList)) {
        industryTemplateDTO.setSheetDesc(JSON.toJSONString(sheetList));
      }
      industryTemplateDTO.setUploadStatus(UPLOAD_FINISHED);
      industryTemplateDTO.setTplId(tplId);

      industryTemplateService.updateByTplId(industryTemplateDTO);
    } catch (Exception e) {
      LOG.error("上传行业模板异常:" + e.getMessage(), e);

      industryTemplateDTO.setUploadStatus(UPLOAD_ERROR);
      industryTemplateDTO.setTplId(tplId);

      industryTemplateService.updateByTplId(industryTemplateDTO);

      File dir = new File(industryTemplateDTO.getFileUrl());
      FileUtils.deleteQuietly(dir);
    }
  }

  /**
   * 处理行业模板实体类
   * 
   * @param fileName
   * @param absolutePath
   * @param uploadId
   * @param comments
   * @return
   */
  private IndustryTemplateDTO handleIndustryTemplate(String fileName, String absolutePath,
      String uploadId, String comments) {
    IndustryTemplateDTO industryTemplateDTO = new IndustryTemplateDTO();

    industryTemplateDTO.setTplId(Utils.getRequestNo());
    industryTemplateDTO.setTplNm(fileName);
    industryTemplateDTO.setFileUrl(absolutePath);
    industryTemplateDTO.setUploadId(uploadId);
    industryTemplateDTO.setRemrk(comments);
    industryTemplateDTO.setDelInd(new BigDecimal(0));
    industryTemplateDTO.setUploadStatus(UPLOAD_UNFINISHED);

    return industryTemplateDTO;
  }

  /**
   * 配置行业模板
   *
   * @return
   */
  @PostMapping(value = "/configureIndustryTemplate")
  @OptLog(logType = LogTypeEnum.OPERATION, module = "autoPackage", description = "配置行业模板")
  public ServerResponse configureIndustryTemplate(@RequestBody IndustryTemplateVO excelVo) {
    ExcelTemplate newExc = new ExcelTemplate();
    try {
      SysUsr user = ContextHolderUtils.getLoginUser();

      String uploadPath = System.getProperty(templatePath);
      String basePath = UPLOAD + File.separator;
      String personalPath = basePath + user.getUsrId() + File.separator;
      String uploadDir = uploadPath + File.separator + personalPath;
      String target = uploadDir + ExcelOperateUtil.getFileName(excelVo.getFilePath());

      newExc = handleEntity(excelVo, excelVo.getProjectName(), user.getUsrId(), target);
      newExc.setUploadStatus(UPLOAD_UNFINISHED);

      String tplId = newExc.getTplId();

      excelTemplateService.insertClientManage(user, newExc, "", new Project());

      threadPool.execute(() -> configureIndustryTemplateThread(excelVo, tplId, target));

      return ServerResponse.createBySuccess();
    } catch (Exception e) {
      LOG.error("配置行业模板异常:" + e.getMessage(), e);
      File dir = new File(newExc.getFileUrl());
      FileUtils.deleteQuietly(dir);
      return ServerResponse.createByErrorMessage("行业模板配置异常");
    }
  }

  /**
   * 配置行业模板
   *
   * @return
   */
  private void configureIndustryTemplateThread(IndustryTemplateVO excelVo, String tplId,
      String target) {
    ExcelTemplate newExc = new ExcelTemplate();
    try {
      JSONArray jsonArray = JSON.parseArray(excelVo.getSelect());
      Workbook workbook = ExcelOperateUtil.getWorkbook(excelVo.getFilePath());
      String[] totalSheetArr = ExcelOperateUtil.getSheets(workbook);

      int size = jsonArray.size();
      int totalSize = totalSheetArr.length;

      String[] select;
      String[] unSelect;
      if (ArrayUtils.contains(totalSheetArr, DESCRIPTION)) {
        unSelect = new String[(totalSize - size - 1)];
        select = new String[size + 1];
        select[size] = DESCRIPTION;
      } else {
        select = new String[size];
        unSelect = new String[(totalSize - size)];
      }

      for (int i = 0; i < size; i++) {
        JSONObject jsonObject = (JSONObject) jsonArray.get(i);
        String sheetName = jsonObject.getString(SHEET_NAME);
        select[i] = sheetName;
      }

      totalSheetArr = ArrayUtils.removeElement(totalSheetArr, DESCRIPTION);
      int j = 0;
      for (int i = 0; i < totalSheetArr.length; i++) {
        if (!ArrayUtils.contains(select, totalSheetArr[i])) {
          unSelect[j++] = totalSheetArr[i];
        }
      }

      ExcelOperateUtil.createCustomTemplate(workbook, target, select, unSelect);

      // 行业模板修改，目标模板联动修改
      select = ArrayUtils.removeElement(select, DESCRIPTION);
      String[] newTotalArr = ArrayUtils.addAll(select, unSelect);
      List<Map<String, String>> sheetNameList =
          ExcelOperateUtil.getSheetNameList(workbook, newTotalArr);

      List<Map<String, String>> sheetList = ExcelOperateUtil.convertJsonArrayToList(jsonArray);
      newExc.setSelectSheet(JSON.toJSONString(sheetList));

      // 获取sheet页描述数组
      StringBuilder totalSheet = new StringBuilder();

      if (!ArrayUtils.isEmpty(totalSheetArr)) {
        Arrays.stream(totalSheetArr).forEach(arr -> totalSheet.append(arr).append(SPLIT_SIGN));
      }

      if (!StringUtils.isEmpty(totalSheet)) {
        newExc.setTotalSheet(totalSheet.toString().substring(0, totalSheet.length() - 1));
      }
      if (!CollectionUtils.isEmpty(sheetNameList)) {
        newExc.setSheetDesc(JSON.toJSONString(sheetNameList));
      }
      newExc.setUploadStatus(UPLOAD_FINISHED);
      newExc.setTplId(tplId);

      excelTemplateService.updateByTplId(newExc);
    } catch (Exception e) {
      LOG.error("配置行业模板异常:" + e.getMessage(), e);

      newExc.setUploadStatus(UPLOAD_ERROR);
      newExc.setTplId(tplId);

      excelTemplateService.updateByTplId(newExc);

      File dir = new File(newExc.getFileUrl());
      FileUtils.deleteQuietly(dir);
    }
  }

  /**
   * 处理目标模板实体类
   * 
   * @param excelVo
   * @param clientName
   * @param uploadId
   * @param target
   * @return
   */
  private ExcelTemplate handleEntity(IndustryTemplateVO excelVo, String clientName, String uploadId,
      String target) {
    ExcelTemplate newExc = new ExcelTemplate();

    newExc.setClientId(excelVo.getProjectId());
    newExc.setClientNm(clientName);
    newExc.setUploadId(uploadId);
    newExc.setTplId(Utils.getRequestNo());
    newExc.setTplNm(excelVo.getFileName());
    newExc.setFileUrl(target);
    newExc.setIndustryId(excelVo.getTplMgtId());
    newExc.setTplType(new BigDecimal(1));
    if (StringUtils.isEmpty(excelVo.getRemark())) {
      newExc.setRemark("");
    } else {
      newExc.setRemark(excelVo.getRemark().trim());
    }
    newExc.setDelInd(new BigDecimal(0));

    return newExc;
  }

  /**
   * 新增行业模板
   */
  @PostMapping(value = "/addIndustryTemplate")
  public ServerResponse addIndustryTemplate(
      @RequestParam("selectedTemplate") MultipartFile bookSetFile,
      @RequestBody IndustryTemplateVO excelVo) {
    try {
      // 获取用户项目信息
      SysUsr user = ContextHolderUtils.getLoginUser();

      String uploadPath = System.getProperty(templatePath);
      String absolutePath = ExcelOperateUtil.handleFileStream(bookSetFile, uploadPath, user);

      IndustryTemplateDTO industryTemplateDTO = new IndustryTemplateDTO();

      industryTemplateDTO.setTplId(Utils.getRequestNo());
      industryTemplateDTO.setTplNm(excelVo.getTplNm());
      industryTemplateDTO.setFileUrl(absolutePath);
      industryTemplateDTO.setUploadId(user.getUsrId());
      if (StringUtils.isEmpty(excelVo.getRemark())) {
        industryTemplateDTO.setRemrk("");
      } else {
        industryTemplateDTO.setRemrk(excelVo.getRemark().trim());
      }
      industryTemplateDTO.setDelInd(new BigDecimal(0));

      return industryTemplateService.insertIndustryTemplate(industryTemplateDTO);
    } catch (Exception e) {
      LOG.error("新增行业模板异常:" + e.getMessage(), e);
      return ServerResponse.createByErrorMessage("新增行业模板异常");
    }
  }

  /**
   * 编辑行业模板
   */
  @PostMapping(value = "/editIndustryTemplate")
  @OptLog(logType = LogTypeEnum.OPERATION, module = "autoPackage", description = "修改行业模板")
  public ServerResponse editIndustryTemplate(MultipartFile file, String fileName, String comments,
      String tplId) {
    IndustryTemplateDTO industryTemplateDTO = new IndustryTemplateDTO();
    try {
      // 获取用户项目信息
      SysUsr user = ContextHolderUtils.getLoginUser();
      String userId = user.getUsrId();

      if (file != null) {
        String uploadPath = System.getProperty(templatePath);
        String absolutePath = ExcelOperateUtil.handleFileStream(file, uploadPath, user);
        industryTemplateDTO.setFileUrl(absolutePath);
        industryTemplateDTO.setTplNm(fileName);
        industryTemplateDTO.setRemrk(comments);
        industryTemplateDTO.setUploadId(user.getUsrId());
        industryTemplateDTO.setTplMgtId(tplId);
        industryTemplateDTO.setUploadStatus(UPLOAD_UNFINISHED);

        industryTemplateService.updateIndustryTemplate(industryTemplateDTO);

        threadPool.execute(() -> editIndustryTemplateThread(absolutePath, tplId, userId));

        return ServerResponse.createBySuccess();
      } else {
        industryTemplateDTO.setTplNm(fileName);
        industryTemplateDTO.setRemrk(comments);
        industryTemplateDTO.setTplMgtId(tplId);

        industryTemplateService.updateIndustryTemplate(industryTemplateDTO);

        return ServerResponse.createBySuccess();
      }
    } catch (Exception e) {
      LOG.error("编辑行业模板异常:" + e.getMessage(), e);

      industryTemplateDTO.setUploadStatus(UPLOAD_ERROR);
      industryTemplateService.updateIndustryTemplate(industryTemplateDTO);

      File dir = new File(industryTemplateDTO.getFileUrl());
      FileUtils.deleteQuietly(dir);

      return ServerResponse.createByErrorMessage("编辑行业模板异常");
    }
  }

  /**
   * 编辑行业模板
   * 
   * @param absolutePath
   * @param tplId
   */
  private void editIndustryTemplateThread(String absolutePath, String tplId, String userId) {
    IndustryTemplateDTO industryTemplateDTO = new IndustryTemplateDTO();
    try {
      // 获取用户项目信息
      SysUsr user = new SysUsr();
      user.setUsrId(userId);

      Workbook workbook = ExcelOperateUtil.getWorkbook(absolutePath);
      String[] totalSheetArr = ExcelOperateUtil.getSheets(workbook);
      totalSheetArr = ArrayUtils.removeElement(totalSheetArr, DESCRIPTION);


      // 获取sheet页描述数组
      StringBuilder totalSheet = new StringBuilder();
      if (!ArrayUtils.isEmpty(totalSheetArr)) {
        Arrays.stream(totalSheetArr).forEach(arr -> totalSheet.append(arr).append(SPLIT_SIGN));
      }

      List<Map<String, String>> sheetList = getSheetList(workbook, totalSheetArr);

      String totalSheetList = totalSheet.toString().substring(0, totalSheet.length() - 1);
      if (!StringUtils.isEmpty(totalSheet)) {
        industryTemplateDTO.setTotalSheet(totalSheetList);
      }
      if (!CollectionUtils.isEmpty(sheetList)) {
        industryTemplateDTO.setSheetDesc(JSON.toJSONString(sheetList));
      } else {
        industryTemplateDTO.setSheetDesc("");
      }
      industryTemplateDTO.setFileUrl(absolutePath);
      industryTemplateDTO.setUploadStatus(UPLOAD_FINISHED);
      industryTemplateDTO.setTplMgtId(tplId);

      industryTemplateService.updateIndustryTemplate(industryTemplateDTO);

      editClientManage(tplId, industryTemplateDTO, totalSheetList, user);
    } catch (Exception e) {
      LOG.error("编辑行业模板异常:" + e.getMessage(), e);
    }
  }

  /**
   * 获取sheet页集合
   * 
   * @param workbook
   * @param totalSheetArr
   * @return
   */
  private List<Map<String, String>> getSheetList(Workbook workbook, String[] totalSheetArr) {
    List<Map<String, String>> sheetList = new ArrayList<>();
    // 获取sheet描述
    String cellStr;
    String cellSheetName;

    String[] cellSheetNameArr = {};
    cellStr = ExcelOperateUtil.getCellDesc(workbook);

    String[] cellSheetDescArr = cellStr.split(SPLIT_SIGN);
    if (!StringUtils.isEmpty(cellStr)) {
      cellSheetName = ExcelOperateUtil.getCellName(workbook);
      if (cellSheetName.contains(SPLIT_SIGN)) {
        cellSheetNameArr = cellSheetName.split(SPLIT_SIGN);
      }
    }

    if (!ArrayUtils.isEmpty(totalSheetArr) && !ArrayUtils.isEmpty(cellSheetNameArr)) {
      sheetList = ExcelOperateUtil.convertArrayToList(cellSheetNameArr, cellSheetDescArr);
    }

    return sheetList;
  }

  /**
   * 编辑目标模板
   * 
   * @param tplId
   * @param industryTemplateDTO
   * @param totalSheetList
   * @param user
   * @throws FileNotFoundException
   * @throws InterruptedException
   */
  private void editClientManage(String tplId, IndustryTemplateDTO industryTemplateDTO,
      String totalSheetList, SysUsr user) throws FileNotFoundException, InterruptedException {
    List<ExcelTemplate> excelTemplates = excelTemplateService.selectById(tplId);

    String sheetDesc = industryTemplateDTO.getSheetDesc();
    if (!CollectionUtils.isEmpty(excelTemplates)) {
      for (ExcelTemplate excelTemplate : excelTemplates) {
        ExcelTemplate newExc = new ExcelTemplate();
        newExc.setTotalSheet(totalSheetList);
        newExc.setSheetDesc(sheetDesc);
        newExc.setTplMgtId(excelTemplate.getTplMgtId());
        excelTemplateService.editClientManage(user, newExc, "", new Project());
      }
    }
  }

  /**
   * 删除行业模板
   */
  @PostMapping(value = "/delIndustryTemplate")
  @OptLog(logType = LogTypeEnum.OPERATION, module = "autoPackage", description = "删除行业模板")
  public ServerResponse delIndustryTemplate(@RequestBody IndustryTemplateVO excelVo) {
    try {
      // 获取用户项目信息
      SysUsr user = ContextHolderUtils.getLoginUser();

      IndustryTemplateDTO industryTemplateDTO = new IndustryTemplateDTO();

      industryTemplateDTO.setUploadId(user.getUsrId());
      industryTemplateDTO.setDelInd(new BigDecimal(1));
      industryTemplateDTO.setTplMgtId(excelVo.getTplMgtId());

      return industryTemplateService.updateIndustryTemplate(industryTemplateDTO);
    } catch (Exception e) {
      LOG.error("删除行业模板异常:" + e.getMessage(), e);
      return ServerResponse.createByErrorMessage("删除行业模板异常");
    }
  }

  /**
   * 下载行业模板
   * 
   * @param industryTemplateVO
   * @param request
   * @param response
   */
  @ApiOperation(value = "下载文件", notes = "下载文件")
  @PostMapping(value = "/downloadIndustryTemplate")
  @OptLog(logType = LogTypeEnum.OPERATION, module = "autoPackage", description = "下载行业模板")
  public void requestResultDownload(@RequestBody IndustryTemplateVO industryTemplateVO,
      HttpServletRequest request, HttpServletResponse response) {
    String tplNm = industryTemplateVO.getTplNm();
    String filePath = industryTemplateVO.getFileUrl();

    ResponseUtils.setZipDownloadResponseHeader(tplNm + ".xlsx", request, response);

    try (FileInputStream inputStream = new FileInputStream(filePath)) {
      IOUtils.copy(inputStream, response.getOutputStream());
      response.flushBuffer();
    } catch (Exception e) {
      LOG.error("下载行业模板失败:" + e.getMessage(), e);
    }
  }
}
